package com.hhxy.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class RedisTool {

	// 解锁的语句
	private static final String DEL_KEY_SCRPIT = 
			"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

    /**
     * 尝试获取分布式锁
     * @param lockKey 锁
     * @param value 值
     * @param expireTime 超期时间, 毫秒
     * @throws Exception 获取锁超时
     */
    public static void tryGetDistributedLock(StringRedisTemplate template, String lockKey
    		, String value, int expireTime) throws Exception {
    	if (!StringUtils.hasText(lockKey) 
    			|| !StringUtils.hasText(value)
    			|| expireTime < 10) {
			throw new IllegalArgumentException("lockKey, value can't null and expireTime >= 10");
		}
    	boolean flag = false;
    	long expire = System.currentTimeMillis() + expireTime;
    	while ((System.currentTimeMillis() < expire)) {
    		flag = template.opsForValue().setIfAbsent(lockKey, value);
    		if (flag) {
    			template.opsForValue().set(lockKey, value, expireTime, TimeUnit.MILLISECONDS);
    			break;
			}
    	}
    	if (!flag) {
			throw new Exception("get redis key lock time out");
		}
    }
    
    /**
     * 释放redis key的锁， 只有当key和value一致时才释放
     * @param template 
     * @param lockKey 要释放的key
     * @param value 要释放的值
     */
    public static void releaseLock(StringRedisTemplate template, String lockKey, String value) {
    	if (!StringUtils.hasText(lockKey) && !StringUtils.hasText(value)) {
			throw new IllegalArgumentException("lockKey, value can't null");
		}
    	DefaultRedisScript<Long> script = new DefaultRedisScript<>(DEL_KEY_SCRPIT);
    	script.setResultType(Long.class);
    	template.execute(script, Collections.singletonList(lockKey), value);
    }
	
}
